package voice

import (
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/httplib"
	"github.com/astaxie/beego/logs"
	"smart_home/api/models"
	"smart_home/api/utils"
	"strconv"
	"sync"
	"time"
	"tools"
	"xfyun"
)

var soundCache = sync.Map{}
var scene = "main"
var cacheKey = "xfyun-voidc-%s-%s"

/*
code	string	结果码(具体见错误码)
data	array	结果数据
desc	string	描述
sid	string	会话ID
*/
type custom struct {
	Code string       `json:"code"`
	Data []customData `json:"data"`
	Desc string       `json:"desc"`
	Sid  string       `json:"sid"`
}

/*
sub	string	业务类型：iat（识别），nlp（语义），tpp（后处理），itrans（翻译）
text	object/string	识别结果：详细结果（object），精简结果（string）
intent	object	语义结果
content	object/string	后处理 (string)，翻译 (object)等结果
result_id	number	结果序号，同一业务逐渐递增
*/
type customData struct {
	Sub      string                 `json:"sub"`
	Text     interface{}            `json:"text"`
	Intent   map[string]interface{} `json:"intent"`
	Content  interface{}            `json:"content"`
	ResultId int64                  `json:"result_id"`
}

// xfyun_after response
type response struct {
	Answer response_answer `json:"answer"`
	Data   interface{}     `json:"data"`
}

type response_answer struct {
	Text string `json:"text"`
	Type string `json:"type"`
}

func (c *custom) getIntent() map[string]interface{} {
	intent := make(map[string]interface{})
	for _, v := range c.Data {
		if v.Sub == "nlp" && len(v.Intent) > len(intent) {
			intent = v.Intent
		}
	}
	return intent
}

func Begin(sta, order string, body []byte) {
	if string(body) != "begin" {
		return
	}
}

func Queue(sta, order string, body []byte) {
	if string(body) == "begin" || string(body) == "end" {
		return
	}
	key := fmt.Sprintf(cacheKey, sta, order)
	//soundCache.Store(key, body)
	// 存在时间20s
	utils.Cache.Put(key, body, 20 * time.Second)
}

func End(sta, order string, body []byte) {
	if string(body) != "end" {
		return
	}

	// 等待100毫秒 防止end提前收到，而数据还没接收完成
	<-time.After(100 * time.Millisecond)

	// 找出设备
	equipment, err := models.GetEquipmentBySta(sta)
	if err != nil {
		return
	}
	if equipment == nil {
		return
	}

	// 语音文件总数
	count, _ := strconv.Atoi(order)

	// 对语音slice排序组合成string
	paylod := []byte("")
	for i := 1; i < count; i++ {
		// 获取语音文件
		key := fmt.Sprintf(cacheKey, sta, strconv.Itoa(i))
		//data, ok := soundCache.Load(key)
		data := utils.Cache.Get(key)

		// 判断语音文件是否存在，存在则合并文件，不存在则跳出识别
		if data == nil {
			logs.Error("client_id %s say error: 语音文件%d为空", sta, i)
			break
		}

		paylod = tools.BytesCombine(paylod, data.([]byte))

		// 删除语音文件
		//soundCache.Delete(key)
		utils.Cache.Delete(key)
	}

	//
	userParams := map[string]interface{}{
		"user_id":     equipment.UserId,
		"sta":         equipment.Sta,
		"device_type": equipment.Type,
	}

	res, err := xfyun.NewAiui().
		SetAuthId(sta).
		SetUserParams(userParams).
		SetScene(scene).
		Audio(paylod)

	custom := &custom{}
	if err := json.Unmarshal([]byte(res), custom); err != nil {
		logs.Error(err)
		return
	}

	if custom.Code != "0" {
		logs.Error("xfyun error:", res)
		return
	}

	hr, err := httplib.Post("http://api.rcenet.com/v2/xfyun/after/custom").JSONBody(custom.getIntent())
	resp := &response{}
	if err := hr.ToJSON(resp); err != nil {
		logs.Error("xfyun after error:", err)
		return
	}

	logs.Debug("resp: %+v", resp)

	// 如果设备的类型不是无外放设备 则下发数据
	if equipment.Type != 1 {

	}
}
